using System;
using System.Reflection;
namespace ServiceStack.Reflection
{
	public static class PropertyAccessor
	{
		public static Func<TEntity, object> GetPropertyFn<TEntity>(string propertyName)
		{
			return new PropertyAccessor<TEntity>(propertyName).GetPropertyFn();
		}
		public static Action<TEntity, object> SetPropertyFn<TEntity>(string propertyName)
		{
			return new PropertyAccessor<TEntity>(propertyName).SetPropertyFn();
		}
	}
	public class PropertyAccessor<TEntity>
	{
		private readonly PropertyInfo pi;
		private readonly Func<TEntity, object> getPropertyFn;
		private readonly Action<TEntity, object> setPropertyFn;
		public string Name
		{
			get;
			set;
		}
		public Type PropertyType
		{
			get;
			set;
		}
		public PropertyAccessor(string propertyName)
		{
			this.pi = typeof(TEntity).GetPropertyInfo(propertyName);
			this.Name = propertyName;
			this.PropertyType = this.pi.PropertyType;
			this.getPropertyFn = StaticAccessors<TEntity>.ValueUnTypedGetPropertyTypeFn(this.pi);
			this.setPropertyFn = StaticAccessors<TEntity>.ValueUnTypedSetPropertyTypeFn(this.pi);
		}
		public Func<TEntity, object> GetPropertyFn()
		{
			return this.getPropertyFn;
		}
		public Action<TEntity, object> SetPropertyFn()
		{
			return this.setPropertyFn;
		}
		public Func<TEntity, TId> TypedGetPropertyFn<TId>()
		{
			return StaticAccessors<TEntity>.TypedGetPropertyFn<TId>(this.pi);
		}
		public Func<TEntity, object> ValueTypedGetPropertyFn<TId>()
		{
			return StaticAccessors<TEntity>.ValueUnTypedGetPropertyFn<TId>(this.pi);
		}
		public Func<object, object> UnTypedGetPropertyFn<TId>()
		{
			return StaticAccessors<TEntity>.UnTypedGetPropertyFn<TId>(this.pi);
		}
		public Action<TEntity, TId> TypedSetPropertyFn<TId>()
		{
			return StaticAccessors<TEntity>.TypedSetPropertyFn<TId>(this.pi);
		}
		public Action<TEntity, object> ValueTypesSetPropertyFn<TId>()
		{
			return StaticAccessors<TEntity>.ValueUnTypedSetPropertyFn<TId>(this.pi);
		}
		public Action<object, object> UnTypedSetPropertyFn<TId>()
		{
			return StaticAccessors<TEntity>.UnTypedSetPropertyFn<TId>(this.pi);
		}
	}
}
